package de.tsajar.es.networking.serializer;

import com.jme3.network.serializing.Serializer;
import com.simsilica.es.ComponentFilter;
import com.simsilica.es.Entity;
import com.simsilica.es.EntityComponent;
import com.simsilica.es.EntityId;
import com.simsilica.es.Filters;
import com.simsilica.es.filter.AndFilter;
import com.simsilica.es.filter.FieldFilter;
import com.simsilica.es.filter.OrFilter;
import de.tsajar.es.networking.ReadOnlyEntity;
import java.io.IOException;
import java.nio.ByteBuffer;

/**
 * Serializer for Entities and ComponentFilters
 * @author Eike Foede
 */
public class EntitySystemSerializer extends Serializer {

    @Override
    public <T> T readObject(ByteBuffer data, Class<T> c) throws IOException {
        if (c.isAssignableFrom(Entity.class)) {//Entity
            EntityId id = new EntityId(data.getLong());
            int size = data.getInt();
            EntityComponent[] comp = new EntityComponent[size];
            for (int i = 0; i < comp.length; i++) {
                comp[i] = (EntityComponent) Serializer.readClassAndObject(data);
            }
            return (T) new ReadOnlyEntity(id, comp);
        } else if (c.isAssignableFrom(FieldFilter.class)) {//FieldFilter
            Class type = (Class) Serializer.readClassAndObject(data);
            String field = (String) Serializer.readClassAndObject(data);
            Object value = Serializer.readClassAndObject(data);
            ComponentFilter ff = Filters.fieldEquals(type, field, value);
            return (T) ff;
        } else if (c.isAssignableFrom(OrFilter.class)) {//OrFilter
            System.out.println("Or");
            Class type = (Class) Serializer.readClassAndObject(data);

            int size = data.getInt();
            ComponentFilter[] comp = new ComponentFilter[size];
            for (int i = 0; i < comp.length; i++) {
                comp[i] = (ComponentFilter) Serializer.readClassAndObject(data);
            }
            return (T) Filters.or(type, comp);
        } else if (c.isAssignableFrom(AndFilter.class)) {//AndFilter
            Class type = (Class) Serializer.readClassAndObject(data);

            int size = data.getInt();
            ComponentFilter[] comp = new ComponentFilter[size];
            for (int i = 0; i < comp.length; i++) {
                comp[i] = (ComponentFilter) Serializer.readClassAndObject(data);
            }
            return (T) Filters.and(type, comp);
        } else {
            throw new IOException("Requested class is not supported!");

        }
    }

    @Override
    public void writeObject(ByteBuffer buffer, Object object) throws IOException {
        if (object instanceof Entity) {//Entity
            Entity e = (Entity) object;
            buffer.putLong(e.getId().getId());
            buffer.putInt(e.getComponents().length);
            for (EntityComponent ec : e.getComponents()) {
                Serializer.writeClassAndObject(buffer, ec);
            }
        } else if (object instanceof FieldFilter) {//FieldFilter
            FieldFilter ff = (FieldFilter) object;
            Serializer.writeClassAndObject(buffer, ff.getComponentType());
            Serializer.writeClassAndObject(buffer, ff.getFieldName());
            Serializer.writeClassAndObject(buffer, ff.getValue());

        } else if (object instanceof OrFilter) {//OrFilter
            OrFilter of = (OrFilter) object;
            Serializer.writeClassAndObject(buffer, of.getComponentType());
            buffer.putInt(of.getOperands().length);
            for (ComponentFilter cf : of.getOperands()) {
                Serializer.writeClassAndObject(buffer, cf);
            }
        } else if (object instanceof AndFilter) {//AndFilter
            AndFilter af = (AndFilter) object;
            Serializer.writeClassAndObject(buffer, af.getComponentType());
            buffer.putInt(af.getOperands().length);
            for (ComponentFilter cf : af.getOperands()) {
                Serializer.writeClassAndObject(buffer, cf);
            }
        } else {
            throw new IOException("Unsupported class!");

        }
    }
}
